package com.coderside.fragment.ref;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;

import junit.framework.Assert;
import test.HelloWorld;

public class RerferenceTest {
	@org.junit.Test
	public void hello() {
		System.out.println("Hello world");
		WeakHashMap o = weakReference();
		System.gc();
		o.size();
		System.out.println(o);
	}

	public WeakHashMap weakReference() {
		Object referent = new HelloWorld();
		WeakReference<Object> weakRerference = new WeakReference<Object>(referent);
		WeakHashMap<WeakReference<Object>, Object> map = new WeakHashMap<WeakReference<Object>, Object>();
		//		Assert.assertSame(referent, weakRerference.get());
		map.put(weakRerference, weakRerference.get());
		referent = null;
		//		System.gc();
		System.out.println(map.size());
		/**
		 * 一旦没有指向 referent 的强引用, weak reference 在 GC 后会被自动回收
		 */
		return map;
	}

	@org.junit.Test
	public void softReference() {
		Object referent = new HelloWorld();
		SoftReference<Object> softRerference = new SoftReference<Object>(referent);

		Assert.assertNotNull(softRerference.get());

		referent = null;
		System.gc();

		/**
		 *  soft references 只有在 jvm OutOfMemory 之前才会被回收, 所以它非常适合缓存应用
		 */
		Assert.assertNotNull(softRerference.get());
	}

	@org.junit.Test
	public void strongReference() {
		Object referent = new Object();

		/**
		 * 通过赋值创建 StrongReference 
		 */
		Object strongReference = referent;

		Assert.assertSame(referent, strongReference);

		referent = null;
		System.gc();

		/**
		 * StrongReference 在 GC 后不会被回收
		 */
		Assert.assertNotNull(strongReference);
	}

	@org.junit.Test
	public void weakHashMap() throws InterruptedException {
		Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();
		Object key = new Object();
		Object value = new Object();
		weakHashMap.put(key, value);

		Assert.assertTrue(weakHashMap.containsValue(value));

		key = null;
		System.gc();

		/**
		 * 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理
		 */
		Thread.sleep(1000);

		/**
		 * 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry
		 */
		Assert.assertFalse(weakHashMap.containsValue(value));
	}
}
